﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using A2DFramework.ServiceLocatorService.Configuration;

namespace A2DFramework.ServiceLocatorService
{
    public class ServiceLocator
    {
        private static Dictionary<string, Service> serviceCache = new Dictionary<string, Service>();
        internal static void ClearCache()
        {
            serviceCache.Clear();
        }


        //public static Location Locate(string contractNamespace, string contract)
        //{
        //    return Locate(contractNamespace, contract, string.Empty);
        //}

        /// <summary>
        /// 根据Contract的命名空间及Contract名找到服务的真实地址信息
        /// </summary>
        /// <param name="contractNamespace"></param>
        /// <param name="contract"></param>
        /// <param name="version"></param>
        /// <returns></returns>
        public static Location Locate(string contractNamespace, string contract, string version)
        {
            Service srv=null;

            string key = string.Format("{0}.{1}", contractNamespace, contract);
            if (!serviceCache.ContainsKey(key))
            {
                srv = FindService(contractNamespace, contract, srv);
                serviceCache[key] = srv;
            }
            else
            { 
                srv=serviceCache[key];
            }
            if(srv.Urls==null||srv.Urls.Count==0)
                throw new Exception(string.Format("Service' url not found [{0}.{1}]", contractNamespace, contract));

            Url url = null;
            if (string.IsNullOrEmpty(version))
                url = srv.Urls.Find(w => string.IsNullOrEmpty(w.Version));
            else
                url = srv.Urls.Find(w => w.Version!=null&&w.Version.Equals(version, StringComparison.OrdinalIgnoreCase));

            Location location = new Location();
            location.EndpointType = url.EndpointType;
            location.Url = url.ReferenceUrl;
            location.AssemblyPath = srv.AssemblyPath;
            return location;
        }

        private static Service FindService(string contractNamespace, string contract, Service srv)
        {
            List<Service> matchedServices = LocatorServiceConfiguration.Services.Where(t =>
                    t.Contract.CompareTo(contract) == 0
                    &&
                    t.ContractNamespace.CompareTo(contractNamespace) == 0
            ).ToList();

            if (matchedServices == null || matchedServices.Count == 0)
                throw new Exception(string.Format("Service not found [{0}.{1}]", contractNamespace, contract));

            srv = matchedServices.First();
            return srv;
        }
    }
}
